﻿using System;
using System.Collections.Generic;
using System.Web;

namespace GMobile
{
    public class Detector
    {
        private string _userAgent = "";
        private string _httpAccept = "";

        #region Fields - Detection Argument Values

        //standardized values for detection arguments.
        private const string dargsIphone = "iphone";
        private const string dargsIpod = "ipod";
        private const string dargsIpad = "ipad";
        private const string dargsIphoneOrIpod = "iphoneoripod";
        private const string dargsIos = "ios";
        private const string dargsAndroid = "android";
        private const string dargsAndroidPhone = "androidphone";
        private const string dargsAndroidTablet = "androidtablet";
        private const string dargsGoogleTV = "googletv";
        private const string dargsWebKit = "webkit";
        private const string dargsSymbianOS = "symbianos";
        private const string dargsS60 = "series60";
        private const string dargsWindowsPhone7 = "windowsphone7";
        private const string dargsWindowsPhone8 = "windowsphone8";
        private const string dargsWindowsMobile = "windowsmobile";
        private const string dargsBlackBerry = "blackberry";
        private const string dargsBlackBerryWebkit = "blackberrywebkit";
        private const string dargsPalmOS = "palmos";
        private const string dargsPalmWebOS = "webos";
        private const string dargsWebOSTablet = "webostablet";
        private const string dargsSmartphone = "smartphone";
        private const string dargsBrewDevice = "brew";
        private const string dargsDangerHiptop = "dangerhiptop";
        private const string dargsOperaMobile = "operamobile";
        private const string dargsWapWml = "wapwml";
        private const string dargsKindle = "kindle";
        private const string dargsMobileQuick = "mobilequick";
        private const string dargsTierTablet = "tiertablet";
        private const string dargsTierIphone = "tieriphone";
        private const string dargsTierRichCss = "tierrichcss";
        private const string dargsTierOtherPhones = "tierotherphones";

        #endregion Fields - Detection Argument Values

        #region Fields - User Agent Keyword Values

        private const string engineWebKit = "WEBKIT";
        private const string deviceIphone = "IPHONE";
        private const string deviceIpod = "IPOD";
        private const string deviceIpad = "IPAD";
        private const string deviceMacPpc = "MACINTOSH"; //Used for disambiguation

        private const string deviceAndroid = "ANDROID";
        private const string deviceGoogleTV = "GOOGLETV";
        private const string deviceHtcFlyer = "HTC_FLYER"; //HTC Flyer

        private const string deviceNuvifone = "NUVIFONE";  //Garmin Nuvifone

        private const string deviceSymbian = "SYMBIAN";
        private const string deviceS60 = "SERIES60";
        private const string deviceS70 = "SERIES70";
        private const string deviceS80 = "SERIES80";
        private const string deviceS90 = "SERIES90";

        private const string deviceWinPhone7 = "WINDOWS PHONE OS 7";
        private const string deviceWinPhone8 = "WINDOWS PHONE 8";
        private const string deviceWinMob = "WINDOWS CE";
        private const string deviceWindows = "WINDOWS";
        private const string deviceIeMob = "IEMOBILE";
        private const string devicePpc = "PPC"; //Stands for PocketPC
        private const string enginePie = "WM5 PIE"; //An old Windows Mobile browser

        private const string deviceBB = "BLACKBERRY";
        private const string vndRIM = "VND.RIM"; //Detectable when BB devices emulate IE or Firefox
        private const string deviceBBStorm = "BLACKBERRY95"; //Storm 1 and 2
        private const string deviceBBBold = "BLACKBERRY97"; //Bold 97x0 (non-touch)
        private const string deviceBBBoldTouch = "BLACKBERRY 99"; //Bold 99x0 (touchscreen)
        private const string deviceBBTour = "BLACKBERRY96"; //Tour
        private const string deviceBBCurve = "BLACKBERRY89"; //Curve2
        private const string deviceBBCurveTouch = "BLACKBERRY 938"; //Curve Touch 9380
        private const string deviceBBTorch = "BLACKBERRY 98"; //Torch
        private const string deviceBBPlaybook = "PLAYBOOK"; //PlayBook tablet
        private const string deviceBB10 = "BB10";//BlackBerry Z10

        private const string devicePalm = "PALM";
        private const string deviceWebOS = "WEBOS"; //For Palm's line of WebOS devices
        private const string deviceWebOShp = "HPWOS"; //For HP's line of WebOS devices

        private const string engineBlazer = "BLAZER"; //Old Palm
        private const string engineXiino = "XIINO"; //Another old Palm

        private const string deviceKindle = "KINDLE";  //Amazon Kindle, eInk one
        private const string engineSilk = "SILK";  //Amazon's accelerated Silk browser for Kindle Fire

        //Initialize private strings for mobile-specific content.
        private const string vndwap = "VND.WAP";
        private const string wml = "WML";

        //Initialize private strings for other random devices and mobile browsers.
        private const string deviceTablet = "TABLET"; //Generic term for slate and tablet devices
        private const string deviceBrew = "BREW";
        private const string deviceDanger = "DANGER";
        private const string deviceHiptop = "HIPTOP";
        private const string devicePlaystation = "PLAYSTATION";
        private const string deviceNintendoDs = "NITRO";
        private const string deviceNintendo = "NINTENDO";
        private const string deviceWii = "WII";
        private const string deviceXbox = "XBOX";
        private const string deviceArchos = "ARCHOS";

        private const string engineOpera = "OPERA"; //Popular browser
        private const string engineNetfront = "NETFRONT"; //Common embedded OS browser
        private const string engineUpBrowser = "UP.BROWSER"; //common on some phones
        private const string engineOpenWeb = "OPENWEB"; //Transcoding by OpenWave server
        private const string deviceMidp = "MIDP"; //a mobile Java technology
        private const string uplink = "UP.LINK";
        private const string engineTelecaQ = "TELECA Q"; //a modern feature phone browser

        private const string devicePda = "PDA"; //some devices report themselves as PDAs
        private const string mini = "MINI";  //Some mobile browsers put "mini" in their names.
        private const string mobile = "MOBILE"; //Some mobile browsers put "mobile" in their user agent private strings.
        private const string mobi = "MOBI"; //Some mobile browsers put "mobi" in their user agent private strings.

        //Use Maemo, Tablet, and Linux to test for Nokia"s Internet Tablets.
        private const string maemo = "MAEMO";
        private const string linux = "LINUX";
        private const string qtembedded = "QT EMBEDDED"; //for Sony Mylo
        private const string mylocom2 = "COM2"; //for Sony Mylo also

        //In some UserAgents, the only clue is the manufacturer.
        private const string manuSonyEricsson = "SONYERICSSON";
        private const string manuericsson = "ERICSSON";
        private const string manuSamsung1 = "SEC-SGH";
        private const string manuSony = "SONY";
        private const string manuHtc = "HTC"; //Popular Android and WinMo manufacturer

        //In some UserAgents, the only clue is the operator.
        private const string svcDocomo = "DOCOMO";
        private const string svcKddi = "KDDI";
        private const string svcVodafone = "VODAFONE";

        //Disambiguation strings.
        private const string disUpdate = "UPDATE"; //pda vs. update

        #endregion Fields - User Agent Keyword Values

        /// <summary>
        /// To instantiate a WebPage sub-class with built-in
        /// mobile device detection delegates and events.
        /// </summary>
        public Detector(string userAgent, string httpAccept)
        {
            _userAgent = userAgent.ToUpper();
            _httpAccept = httpAccept.ToUpper();
        }
        /// <summary>
        /// To instantiate a WebPage sub-class with built-in
        /// mobile device detection delegates and events.
        /// </summary>
        public Detector(HttpContext context)
        {
            _userAgent = GetUserAgentFromRequest(context.Request).ToUpper();
            _httpAccept = (context.Request.ServerVariables["HTTP_ACCEPT"] ?? "").ToUpper();
        }

        #region Mobile Device Detection Methods

        //**************************
        // Detects if the current device is an iPod Touch.
        public bool DetectIpod()
        {
            if (_userAgent.IndexOf(deviceIpod) != -1)
                return true;
            else
                return false;
        }

        //**************************
        // Detects if the current device is an iPad tablet.
        public bool DetectIpad()
        {
            if (_userAgent.IndexOf(deviceIpad) != -1 && DetectWebkit())
                return true;
            else
                return false;
        }

        //**************************
        // Detects if the current device is an iPhone.
        public bool DetectIphone()
        {
            if (_userAgent.IndexOf(deviceIphone) != -1)
            {
                //The iPad and iPod touch say they're an iPhone! So let's disambiguate.
                if (DetectIpad() || DetectIpod())
                {
                    return false;
                }
                else
                    return true;
            }
            else
                return false;
        }

        //**************************
        // Detects if the current device is an iPhone or iPod Touch.
        public bool DetectIphoneOrIpod()
        {
            //We repeat the searches here because some iPods may report themselves as an iPhone, which would be okay.
            if (_userAgent.IndexOf(deviceIphone) != -1 ||
                _userAgent.IndexOf(deviceIpod) != -1)
                return true;
            else
                return false;
        }

        //**************************
        // Detects *any* iOS device: iPhone, iPod Touch, iPad.
        public bool DetectIos()
        {
            if (DetectIphoneOrIpod() || DetectIpad())
                return true;
            else
                return false;
        }

        //**************************
        // Detects *any* Android OS-based device: phone, tablet, and multi-media player.
        // Also detects Google TV.
        public bool DetectAndroid()
        {
            if ((_userAgent.IndexOf(deviceAndroid) != -1) ||
                DetectGoogleTV())
                return true;
            //Special check for the HTC Flyer 7" tablet. It should report here.
            if (_userAgent.IndexOf(deviceHtcFlyer) != -1)
                return true;
            else
                return false;
        }

        //**************************
        // Detects if the current device is a (small-ish) Android OS-based device
        // used for calling and/or multi-media (like a Samsung Galaxy Player).
        // Google says these devices will have 'Android' AND 'mobile' in user agent.
        // Ignores tablets (Honeycomb and later).
        public bool DetectAndroidPhone()
        {
            if (DetectAndroid() &&
                (_userAgent.IndexOf(mobile) != -1))
                return true;
            //Special check for Android phones with Opera Mobile. They should report here.
            if (DetectOperaAndroidPhone())
                return true;
            //Special check for the HTC Flyer 7" tablet. It should report here.
            if (_userAgent.IndexOf(deviceHtcFlyer) != -1)
                return true;
            else
                return false;
        }


        //**************************
        // Detects if the current device is a (self-reported) Android tablet.
        // Google says these devices will have 'Android' and NOT 'mobile' in their user agent.
        public bool DetectAndroidTablet()
        {
            //First, let's make sure we're on an Android device.
            if (!DetectAndroid())
                return false;

            //Special check for Opera Android Phones. They should NOT report here.
            if (DetectOperaMobile())
                return false;
            //Special check for the HTC Flyer 7" tablet. It should NOT report here.
            if (_userAgent.IndexOf(deviceHtcFlyer) != -1)
                return false;

            //Otherwise, if it's Android and does NOT have 'mobile' in it, Google says it's a tablet.
            if (_userAgent.IndexOf(mobile) > -1)
                return false;
            else
                return true;
        }

        //**************************
        // Detects if the current device is a GoogleTV device.
        public bool DetectGoogleTV()
        {
            if (_userAgent.IndexOf(deviceGoogleTV) != -1)
                return true;
            else
                return false;
        }

        //**************************
        // Detects if the current device is an Android OS-based device and
        //   the browser is based on WebKit.
        public bool DetectAndroidWebKit()
        {
            if (DetectAndroid() && DetectWebkit())
                return true;
            else
                return false;
        }

        //**************************
        // Detects if the current browser is based on WebKit.
        public bool DetectWebkit()
        {
            if (_userAgent.IndexOf(engineWebKit) != -1)
                return true;
            else
                return false;
        }

        //**************************
        // Detects if the current browser is the Nokia S60 Open Source Browser.
        public bool DetectS60OssBrowser()
        {
            //First, test for WebKit, then make sure it's either Symbian or S60.
            if (DetectWebkit())
            {
                if (_userAgent.IndexOf(deviceSymbian) != -1 ||
                    _userAgent.IndexOf(deviceS60) != -1)
                {
                    return true;
                }
                else
                    return false;
            }
            else
                return false;
        }

        //**************************
        // Detects if the current device is any Symbian OS-based device,
        //   including older S60, Series 70, Series 80, Series 90, and UIQ, 
        //   or other browsers running on these devices.
        public bool DetectSymbianOS()
        {
            if (_userAgent.IndexOf(deviceSymbian) != -1 ||
                _userAgent.IndexOf(deviceS60) != -1 ||
                _userAgent.IndexOf(deviceS70) != -1 ||
                _userAgent.IndexOf(deviceS80) != -1 ||
                _userAgent.IndexOf(deviceS90) != -1)
                return true;
            else
                return false;
        }

        //**************************
        // Detects if the current browser is a 
        // Windows Phone 7 device.
        public bool DetectWindowsPhone7()
        {
            if (_userAgent.IndexOf(deviceWinPhone7) != -1)
                return true;
            else
                return false;
        }

        //**************************
        // Detects if the current browser is a 
        // Windows Phone 8 device.
        public bool DetectWindowsPhone8()
        {
            if (_userAgent.IndexOf(deviceWinPhone8) != -1)
                return true;
            else
                return false;
        }

        //**************************
        // Detects if the current browser is a Windows Mobile device.
        // Excludes Windows Phone 7 and Windows Phone 8 devices. 
        // Focuses on Windows Mobile 6.xx and earlier.
        public bool DetectWindowsMobile()
        {
            //Exclude new Windows Phone 7.
            if (DetectWindowsPhone7())
                return false;
            //Exclude new Windows Phone 8.
            if (DetectWindowsPhone8())
                return false;
            //Most devices use 'Windows CE', but some report 'iemobile' 
            //  and some older ones report as 'PIE' for Pocket IE. 
            if (_userAgent.IndexOf(deviceWinMob) != -1 ||
                _userAgent.IndexOf(deviceIeMob) != -1 ||
                _userAgent.IndexOf(enginePie) != -1)
                return true;
            //Test for Windows Mobile PPC but not old Macintosh PowerPC.
            if (_userAgent.IndexOf(devicePpc) != -1 &&
                !(_userAgent.IndexOf(deviceMacPpc) != -1))
                return true;
            //Test for certain Windwos Mobile-based HTC devices.
            if (_userAgent.IndexOf(manuHtc) != -1 &&
                _userAgent.IndexOf(deviceWindows) != -1)
                return true;
            if (DetectWapWml() == true &&
                _userAgent.IndexOf(deviceWindows) != -1)
                return true;
            else
                return false;
        }

        //**************************
        // Detects if the current browser is any BlackBerry device.
        // Includes the PlayBook.
        public bool DetectBlackBerry()
        {
            if ((_userAgent.IndexOf(deviceBB) != -1) ||
                (_httpAccept.IndexOf(vndRIM) != -1) || (_userAgent.IndexOf(deviceBB10) != -1))
                return true;
            else
                return false;
        }

        public bool DetectBlackBerry10()
        {
            if (_userAgent.IndexOf(deviceBB10) != -1)
                return true;
            else
                return false;
        }
        //**************************
        // Detects if the current browser is on a BlackBerry tablet device.
        //    Example: PlayBook
        public bool DetectBlackBerryTablet()
        {
            if (_userAgent.IndexOf(deviceBBPlaybook) != -1)
                return true;
            else
                return false;
        }

        //**************************
        // Detects if the current browser is a BlackBerry device AND uses a
        //    WebKit-based browser. These are signatures for the new BlackBerry OS 6.
        //    Examples: Torch. Includes the Playbook.
        public bool DetectBlackBerryWebKit()
        {
            if (DetectBlackBerry() && DetectWebkit())
                return true;
            else
                return false;
        }

        //**************************
        // Detects if the current browser is a BlackBerry Touch
        //    device, such as the Storm, Torch, and Bold Touch. Excludes the Playbook.
        public bool DetectBlackBerryTouch()
        {
            if (DetectBlackBerry() &&
                (_userAgent.IndexOf(deviceBBStorm) != -1 ||
                _userAgent.IndexOf(deviceBBTorch) != -1 ||
                _userAgent.IndexOf(deviceBBBoldTouch) != -1 ||
                _userAgent.IndexOf(deviceBBCurveTouch) != -1) || (_userAgent.IndexOf(deviceBB10) != -1))
                return true;
            else
                return false;
        }

        //**************************
        // Detects if the current browser is a BlackBerry device AND
        //    has a more capable recent browser. Excludes the Playbook.
        //    Examples, Storm, Bold, Tour, Curve2
        //    Excludes the new BlackBerry OS 6 and 7 browser!!
        public bool DetectBlackBerryHigh()
        {
            //Disambiguate for BlackBerry OS 6 or 7 (WebKit) browser
            if (DetectBlackBerryWebKit())
                return false;
            if (DetectBlackBerry())
            {
                if (DetectBlackBerryTouch() ||
                    _userAgent.IndexOf(deviceBBBold) != -1 ||
                    _userAgent.IndexOf(deviceBBTour) != -1 ||
                    _userAgent.IndexOf(deviceBBCurve) != -1 || (_userAgent.IndexOf(deviceBB10) != -1))
                    return true;
                else
                    return false;
            }
            else
                return false;
        }

        //**************************
        // Detects if the current browser is a BlackBerry device AND
        //    has an older, less capable browser. 
        //    Examples: Pearl, 8800, Curve1.
        public bool DetectBlackBerryLow()
        {
            if (DetectBlackBerry())
            {
                //Assume that if it's not in the High tier, then it's Low.
                if (DetectBlackBerryHigh() || DetectBlackBerryWebKit())
                    return false;
                else
                    return true;
            }
            else
                return false;
        }

        //**************************
        // Detects if the current browser is on a PalmOS device.
        public bool DetectPalmOS()
        {
            //Most devices nowadays report as 'Palm', but some older ones reported as Blazer or Xiino.
            if (_userAgent.IndexOf(devicePalm) != -1 ||
                _userAgent.IndexOf(engineBlazer) != -1 ||
                _userAgent.IndexOf(engineXiino) != -1)
            {
                //Make sure it's not WebOS first
                if (DetectPalmWebOS() == true)
                    return false;
                else
                    return true;
            }
            else
                return false;
        }

        //**************************
        // Detects if the current browser is on a Palm device
        //    running the new WebOS.
        public bool DetectPalmWebOS()
        {
            if (_userAgent.IndexOf(deviceWebOS) != -1)
                return true;
            else
                return false;
        }

        //**************************
        // Detects if the current browser is on an HP tablet running WebOS.
        public bool DetectWebOSTablet()
        {
            if (_userAgent.IndexOf(deviceWebOShp) != -1 &&
                _userAgent.IndexOf(deviceTablet) != -1)
            {
                return true;
            }
            else
                return false;
        }

        //**************************
        // Detects if the current browser is a
        //    Garmin Nuvifone.
        public bool DetectGarminNuvifone()
        {
            if (_userAgent.IndexOf(deviceNuvifone) != -1)
                return true;
            else
                return false;
        }


        //**************************
        // Check to see whether the device is any device
        //   in the 'smartphone' category.
        public bool DetectSmartPhone()
        {
            if (DetectIphoneOrIpod() ||
                   DetectAndroidPhone() ||
                   (DetectBlackBerryWebKit() &&
                       DetectBlackBerryTouch()) ||
                       DetectBlackBerry10() ||
                   DetectWindowsPhone7() ||
                   DetectWindowsPhone8() ||
                   DetectPalmWebOS() ||
                   DetectGarminNuvifone())
                return true;
            /*if (DetectIphoneOrIpod() ||
                DetectAndroidPhone() ||
                DetectS60OssBrowser() ||
                DetectSymbianOS() ||
                DetectWindowsMobile() ||
                DetectWindowsPhone7() ||
                DetectWindowsPhone8() ||
                DetectBlackBerry() ||
                DetectPalmWebOS() ||
                DetectPalmOS() ||
                DetectGarminNuvifone())
                return true;*/
            else
                return false;
        }

        //**************************
        // Detects whether the device is a Brew-powered device.
        public bool DetectBrewDevice()
        {
            if (_userAgent.IndexOf(deviceBrew) != -1)
                return true;
            else
                return false;
        }

        //**************************
        // Detects the Danger Hiptop device.
        public bool DetectDangerHiptop()
        {
            if (_userAgent.IndexOf(deviceDanger) != -1 ||
                _userAgent.IndexOf(deviceHiptop) != -1)
                return true;
            else
                return false;
        }


        //**************************
        // Detects if the current browser is Opera Mobile or Mini.
        public bool DetectOperaMobile()
        {
            if (_userAgent.IndexOf(engineOpera) != -1)
            {
                if ((_userAgent.IndexOf(mini) != -1) ||
                 (_userAgent.IndexOf(mobi) != -1))
                {
                    return true;
                }
                else
                    return false;
            }
            else
                return false;
        }

        //**************************
        // Detects if the current browser is Opera Mobile
        // running on an Android phone.
        public bool DetectOperaAndroidPhone()
        {
            if ((_userAgent.IndexOf(engineOpera) != -1) &&
                (_userAgent.IndexOf(deviceAndroid) != -1) &&
                (_userAgent.IndexOf(mobi) != -1))
                return true;
            else
                return false;
        }

        // Detects if the current browser is Opera Mobile
        // running on an Android tablet.
        public bool DetectOperaAndroidTablet()
        {
            if ((_userAgent.IndexOf(engineOpera) != -1) &&
                (_userAgent.IndexOf(deviceAndroid) != -1) &&
                (_userAgent.IndexOf(deviceTablet) != -1))
                return true;
            else
                return false;
        }

        //**************************
        // Detects whether the device supports WAP or WML.
        public bool DetectWapWml()
        {
            if (_httpAccept.IndexOf(vndwap) != -1 ||
                _httpAccept.IndexOf(wml) != -1)
                return true;
            else
                return false;
        }

        //**************************
        // Detects if the current device is an Amazon Kindle (eInk devices only).
        // Note: For the Kindle Fire, use the normal Android methods. 
        public bool DetectKindle()
        {
            if (_userAgent.IndexOf(deviceKindle) != -1 &&
                !DetectAndroid())
                return true;
            else
                return false;
        }

        //**************************
        // Detects if the current Amazon device is using the Silk Browser.
        // Note: Typically used by the the Kindle Fire.
        public bool DetectAmazonSilk()
        {
            if (_userAgent.IndexOf(engineSilk) != -1)
                return true;
            else
                return false;
        }

        //**************************
        //   Detects if the current device is a mobile device.
        //   This method catches most of the popular modern devices.
        //   Excludes Apple iPads and other modern tablets.
        public bool DetectMobileQuick()
        {
            //Let's exclude tablets
            if (DetectTierTablet())
                return false;

            //Most mobile browsing is done on smartphones
            if (DetectSmartPhone())
                return true;

            if (DetectWapWml() ||
                DetectBrewDevice() ||
                DetectOperaMobile())
                return true;

            if ((_userAgent.IndexOf(engineNetfront) != -1) ||
                (_userAgent.IndexOf(engineUpBrowser) != -1) ||
                (_userAgent.IndexOf(engineOpenWeb) != -1))
                return true;

            if (DetectDangerHiptop() ||
                DetectMidpCapable() ||
                DetectMaemoTablet() ||
                DetectArchos())
                return true;

            if ((_userAgent.IndexOf(devicePda) != -1) &&
                (_userAgent.IndexOf(disUpdate) < 0)) //no index found
                return true;
            if (_userAgent.IndexOf(mobile) != -1)
                return true;

            //We also look for Kindle devices
            if (DetectKindle() ||
                DetectAmazonSilk())
                return true;

            else
                return false;
        }

        //**************************
        // Detects if the current device is a Sony Playstation.
        public bool DetectSonyPlaystation()
        {
            if (_userAgent.IndexOf(devicePlaystation) != -1)
                return true;
            else
                return false;
        }

        //**************************
        // Detects if the current device is a Nintendo game device.
        public bool DetectNintendo()
        {
            if (_userAgent.IndexOf(deviceNintendo) != -1 ||
                 _userAgent.IndexOf(deviceWii) != -1 ||
                 _userAgent.IndexOf(deviceNintendoDs) != -1)
                return true;
            else
                return false;
        }

        //**************************
        // Detects if the current device is a Microsoft Xbox.
        public bool DetectXbox()
        {
            if (_userAgent.IndexOf(deviceXbox) != -1)
                return true;
            else
                return false;
        }

        //**************************
        // Detects if the current device is an Internet-capable game console.
        public bool DetectGameConsole()
        {
            if (DetectSonyPlaystation())
                return true;
            else if (DetectNintendo())
                return true;
            else if (DetectXbox())
                return true;
            else
                return false;
        }

        //**************************
        // Detects if the current device supports MIDP, a mobile Java technology.
        public bool DetectMidpCapable()
        {
            if (_userAgent.IndexOf(deviceMidp) != -1 ||
                _httpAccept.IndexOf(deviceMidp) != -1)
                return true;
            else
                return false;
        }

        //**************************
        // Detects if the current device is on one of the Maemo-based Nokia Internet Tablets.
        public bool DetectMaemoTablet()
        {
            if (_userAgent.IndexOf(maemo) != -1)
                return true;
            //For Nokia N810, must be Linux + Tablet, or else it could be something else. 
            else if (_userAgent.IndexOf(linux) != -1 &&
                _userAgent.IndexOf(deviceTablet) != -1 &&
                !DetectWebOSTablet() &&
                !DetectAndroid())
                return true;
            else
                return false;
        }

        //**************************
        // Detects if the current device is an Archos media player/Internet tablet.
        public bool DetectArchos()
        {
            if (_userAgent.IndexOf(deviceArchos) != -1)
                return true;
            else
                return false;
        }

        //**************************
        // Detects if the current browser is a Sony Mylo device.
        public bool DetectSonyMylo()
        {
            if (_userAgent.IndexOf(manuSony) != -1)
            {
                if ((_userAgent.IndexOf(qtembedded) != -1) ||
                 (_userAgent.IndexOf(mylocom2) != -1))
                {
                    return true;
                }
                else
                    return false;
            }
            else
                return false;
        }

        //**************************
        // The longer and more thorough way to detect for a mobile device.
        //   Will probably detect most feature phones,
        //   smartphone-class devices, Internet Tablets, 
        //   Internet-enabled game consoles, etc.
        //   This ought to catch a lot of the more obscure and older devices, also --
        //   but no promises on thoroughness!
        public bool DetectMobileLong()
        {
            if (DetectMobileQuick())
                return true;
            if (DetectGameConsole() ||
                DetectSonyMylo())
                return true;

            //Detect older phones from certain manufacturers and operators. 
            if (_userAgent.IndexOf(uplink) != -1)
                return true;
            if (_userAgent.IndexOf(manuSonyEricsson) != -1)
                return true;
            if (_userAgent.IndexOf(manuericsson) != -1)
                return true;
            if (_userAgent.IndexOf(manuSamsung1) != -1)
                return true;

            if (_userAgent.IndexOf(svcDocomo) != -1)
                return true;
            if (_userAgent.IndexOf(svcKddi) != -1)
                return true;
            if (_userAgent.IndexOf(svcVodafone) != -1)
                return true;

            else
                return false;
        }
        //*****************************
        // For Mobile Web Site Design
        //*****************************

        //**************************
        // The quick way to detect for a tier of devices.
        //   This method detects for the new generation of
        //   HTML 5 capable, larger screen tablets.
        //   Includes iPad, Android (e.g., Xoom), BB Playbook, WebOS, etc.
        public bool DetectTierTablet()
        {
            if (DetectIpad()
                || DetectAndroidTablet()
                || DetectBlackBerryTablet()
                || DetectWebOSTablet())
                return true;
            else
                return false;
        }
        //**************************
        // The quick way to detect for a tier of devices.
        //   This method detects for devices which can 
        //   display iPhone-optimized web content.
        //   Includes iPhone, iPod Touch, Android, Windows Phone 7, WebOS, etc.
        public bool DetectTierIphone()
        {
            if (DetectIphoneOrIpod() ||
                DetectAndroidPhone() ||
                (DetectBlackBerryWebKit() &&
                    DetectBlackBerryTouch()) ||
                DetectWindowsPhone7() ||
                DetectWindowsPhone8() ||
                DetectPalmWebOS() ||
                DetectGarminNuvifone())
                return true;
            else
                return false;
        }
        //**************************
        // The quick way to detect for a tier of devices.
        //   This method detects for devices which are likely to be capable 
        //   of viewing CSS content optimized for the iPhone, 
        //   but may not necessarily support JavaScript.
        //   Excludes all iPhone Tier devices.
        public bool DetectTierRichCss()
        {
            if (DetectMobileQuick())
            {
                //Exclude iPhone Tier and e-Ink Kindle devices
                if (DetectTierIphone() || DetectKindle())
                    return false;

                if (DetectWebkit() ||
                    DetectS60OssBrowser())
                    return true;

                //Note: 'High' BlackBerry devices ONLY
                if (DetectBlackBerryHigh() == true)
                    return true;

                //Older Windows 'Mobile' isn't good enough for iPhone Tier.
                if (DetectWindowsMobile() == true)
                    return true;
                if (_userAgent.IndexOf(engineTelecaQ) != -1)
                    return true;

                else
                    return false;
            }
            else
                return false;
        }
        //**************************
        // The quick way to detect for a tier of devices.
        //   This method detects for all other types of phones,
        //   but excludes the iPhone and Smartphone Tier devices.
        public bool DetectTierOtherPhones()
        {
            if (DetectMobileLong() == true)
            {
                //Exclude devices in the other 2 categories
                if (DetectTierIphone() ||
                    DetectTierRichCss())
                    return false;
                else
                    return true;
            }
            else
                return false;
        }

        //***************************************************************
        #endregion

        string GetUserAgentFromRequest(HttpRequest request)
        {
            try
            {
                string default_UA = request.Headers["User-Agent"] ?? request.ServerVariables["HTTP_USER_AGENT"];
                string x_Opera_UA = request.Headers["X-OperaMini-Phone-UA"];
                string x_device_UA = request.Headers["X-Device-User-Agent"];
                string stock_UA = request.Headers["Device-Stock-UA"];

                if (!String.IsNullOrEmpty(x_Opera_UA))
                {
                    return x_Opera_UA;
                }
                else
                {
                    if (!String.IsNullOrEmpty(x_device_UA))
                    {
                        return x_device_UA;
                    }
                    else if (!String.IsNullOrEmpty(stock_UA))
                    {
                        return stock_UA;
                    }
                    else
                    {
                        return default_UA;
                    }
                }
            }
            catch
            {
                return string.Empty;
            }
        }
    }
}